--百人类游戏工具函数模块

local base = require "base"
local redisdao = require "redisdao"
local filelog = require "filelog"
local skynet = require "skynet"
local queue = require "skynet.queue"
local timetool = require "timetool"
local json = require "cjson"
json.encode_sparse_array(true,1,1)
require "pubenum"


local SlotTool = {}

--锁
local cs_inventory = {}
local cs_income = {}
local cs_profit = {}
local cs_jackpot = {}

--------------------------------------------------
---------------------------

--
--从redis获取系统税率,系统税率在50%~1%之间
--
function SlotTool.get_tax_rate_from_redis(gamename)
    local tax_rate = 0.01   --默认税率0.01
    local key = (gamename or "") .. "_rate"
    local result, result_data = redisdao.query_data(".gmmqredis", "get", key)
    if result and result_data then
        tax_rate = tonumber(result_data) or 0.01
        if tax_rate > 0.5 or tax_rate < 0.01 then
            tax_rate = 0.01
        end
    end

    return tax_rate
end

--
--从redis获取服务费（抽水）比率,抽水率在50%~1%之间
--
function SlotTool.get_service_fee_rate_from_redis(gamename)
    local service_fee_rate = 0.035   --默认抽水率0.035*2
    local key = (gamename or "") .. "_service_fee_rate"
    local result, result_data = redisdao.query_data(".gmmqredis", "get", key)
    if result and result_data then
        service_fee_rate = tonumber(result_data) or 0.035
        if service_fee_rate > 0.5 or service_fee_rate < 0.01 then
            service_fee_rate = 0.035
        end
    end

    return service_fee_rate
end

--
--从redis获取奖池抽水率,奖池抽水率在1%~30%
--
function SlotTool.get_jackpot_rate_from_redis(gamename)
    local jackpot_rate = 0.01   --默认抽水率0.01
    local key = (gamename or "") .. "_jackpot_rate"
    local result, result_data = redisdao.query_data(".gmmqredis", "get", key)
    if result and result_data then
        jackpot_rate = tonumber(result_data) or 0
        if jackpot_rate > 0.3 or jackpot_rate < 0.01 then
            jackpot_rate = 0.01
        end
    end

    return jackpot_rate
end

--
--从redis获取系统库存值
--
function SlotTool.get_inventory_from_redis(gamename)
    local inventory = 0   --默认库存0
    local key = (gamename or "") .. "_system_inventory"
    local result, result_data = redisdao.query_data(".gmmqredis", "get", key)
    if result and result_data then
        inventory = tonumber(result_data) or 0
    end

    return inventory
end

--
--从redis获取系统收入值（主要是参与游戏的机器人的收入值，总收入，不是提取，可正可负）
--
function SlotTool.get_income_from_redis(gamename)
    local income = 0   --默认库存0
    local key = (gamename or "") .. "_system_income"
    local result, result_data = redisdao.query_data(".gmmqredis", "get", key)
    if result and result_data then
        income = tonumber(result_data) or 0
    end

    return income
end

--
--从redis获取系统静态库存值
--静态库存值不存在，则返回动态库存值
--
function SlotTool.get_static_inventory_from_redis(gamename)
    local inventory = 0   --默认库存0
    local key = (gamename or "") .. "_system_static_inventory"
    local result, result_data = redisdao.query_data(".gmmqredis", "get", key)
    if result and result_data then
        inventory = tonumber(result_data) or 0
    else
        inventory = SlotTool.get_inventory_from_redis(gamename)
    end

    return inventory
end

--
--从redis获取奖池
--
function SlotTool.get_jackpot_from_redis(gamename, jackpot_id, is_new)
    local jackpot = 0   --默认0
    local key = (gamename or "") .. "_system_jackpot"
    local result, result_data = redisdao.query_data(".gmmqredis", "hget", key, jackpot_id)
    if result and result_data then
        jackpot = tonumber(result_data) or 0
    end
    if not result_data and is_new then
        redisdao.query_data(".gmmqredis", "hset", key, jackpot_id, jackpot)
    end

    return jackpot
end

--
--获取系统返还率
--
function SlotTool.get_system_rtp(gamename)
    local tax_rate = SlotTool.get_tax_rate_from_redis(gamename)
    local rtp = 1 - tax_rate
    return rtp
end

--
--计算单项返还率（回报率）RTP
--
function SlotTool.calculate_rtp(total_bet, item_bet, item_odds)
    return (( item_bet * item_odds) / total_bet)
end

--
--计算总返还率（回报率）RTP
--
function SlotTool.calculate_total_rtp(total_bet, win_value)
    return (win_value / total_bet)
end

--
--计算总权值
--
function SlotTool.calculate_total_weight(w_list)
    local total_weight = 0
    for id,w in pairs(w_list) do
        total_weight = total_weight + w
    end

    return total_weight
end

--根据权值表，获取随机结果
function SlotTool.get_random_result_by_weightlist(weight_list, total_w)
    total_w = total_w or SlotTool.calculate_total_weight(weight_list)
    local r = base.get_random(1,total_w)
    local sum = 0
    for id,w in pairs(weight_list) do
        sum = sum + w
        if r <= sum then
            return id
        end
    end
    return   
end

--
--更新系统库存值
--
function SlotTool.update_system_inventory(gamename, val, comment)
    --实际修改函数
    local function real_update_system_inventory(gametype, key, val, comment)
        local _,sys_inventory = redisdao.query_data(".gmmqredis", "get", key)
        if not sys_inventory then
            sys_inventory = 0
        else
            sys_inventory = tonumber(sys_inventory) or 0
        end

        --更新库存
        local beginvalue = sys_inventory
        local endvalue = sys_inventory + val
        if beginvalue ~= endvalue then
            redisdao.query_data(".gmmqredis", "set", key, endvalue)
        end

        --记录日志
        local change_type = EGateAction.ADD_INVENTORY  --库存增加
        if val <= 0 then
            change_type = EGateAction.SUB_INVENTORY    --库存减少
        end
        local logstr = string.format("%d,%d,%d,%g,%g,%g,%g,%g,%g,%s,%s,%s,%s", change_type, 0, 0, val, 0, 0, beginvalue, endvalue, 0, comment.table_uuid, comment.start_time, comment.table_tradeid, gamename)
        if gametype == "diamond" then
            skynet.send(".diamondlog", "lua", "write", logstr)
        end

        return true
    end

    --修改
    cs_inventory[gamename] = cs_inventory[gamename] or queue()
    local cs = cs_inventory[gamename]
    local key = (gamename or "") .. "_system_inventory"
    local gametype = string.match(gamename,"_(%a+)")
    
    return cs(real_update_system_inventory, gametype, key, val, comment)   
end

--
--更新系统收入（机器人，总收入，不是提取）
--
function SlotTool.update_system_income(gamename, val, comment)
    --实际修改函数
    local function real_update_system_income(gametype, key, val, comment)
        local _,sys_income = redisdao.query_data(".gmmqredis", "get", key)
        if not sys_income then
            sys_income = 0
        else
            sys_income = tonumber(sys_income) or 0
        end

        --更新库存
        local beginvalue = sys_income
        local endvalue = sys_income + val
        if beginvalue ~= endvalue then
            redisdao.query_data(".gmmqredis", "set", key, endvalue)
        end

        --[[记录日志 机器人不记录日志
        local change_type = EGateAction.ADD_INCOME  --库存增加
        if val <= 0 then
            change_type = EGateAction.SUB_INCOME    --库存减少
        end
        local logstr = string.format("%d,%d,%d,%g,%g,%g,%g,%g,%g,%s,%s,%s", change_type, 0, 0, val, 0, 0, beginvalue, endvalue, 0, comment.table_uuid, comment.start_time, comment.table_tradeid)
        filelog.warn(gametype, logstr)
        if gametype == "diamond" then
            skynet.send(".diamondlog", "lua", "write", logstr)
        end
        --]]

        return true
    end

    --修改
    cs_income[gamename] = cs_income[gamename] or queue()
    local cs = cs_income[gamename]
    local key = (gamename or "") .. "_system_income"
    local gametype = string.match(gamename,"_(%a+)")
    
    return cs(real_update_system_income, gametype, key, val, comment)   
end

--
--更新系统收益
--
function SlotTool.update_system_profit(gamename, inc_val, comment)
    --实际修改函数
    local function real_update_system_profit(gametype, key, inc_val, comment)
        local _,sys_profit = redisdao.query_data(".gmmqredis", "get", key)
        if sys_profit then
            sys_profit = tonumber(sys_profit) or 0
        else
            sys_profit = 0
        end

        --更新
        local beginvalue = sys_profit
        local endvalue = sys_profit + inc_val
        redisdao.query_data(".gmmqredis", "set", key, endvalue)

        --推送到后台
	    --skynet.send(".coinlog", "lua", "write_file_redis", "", 0)

        --记录日志
        local logstr = string.format("%d,%d,%d,%g,%g,%g,%g,%g,%g,%s,%s,%s,%s", EGateAction.ADD_PROFIT, 0, 0, inc_val, 0, 0, beginvalue, endvalue, 0, comment.table_uuid, comment.start_time, comment.table_tradeid, gamename)
        if gametype == "diamond" then
            skynet.send(".diamondlog", "lua", "write", logstr)
        end

        return true
    end

    if inc_val <= 0 then
        return false
    end

    --修改
    cs_profit[gamename] = cs_profit[gamename] or queue()
    local cs = cs_profit[gamename]
    local key = (gamename or "") .. "_system_profit"
    local gametype = string.match(gamename,"_(%a+)")

    return cs(real_update_system_profit, gametype, key, inc_val, comment)
end

--
--更新系统奖池
--
function SlotTool.update_system_jackpot(gamename, val, comment)
    --实际修改函数
    local function real_update_system_jackpot(gametype, key, val, comment)
        local _,sys_jackpot = redisdao.query_data(".gmmqredis", "hget", key, comment.jackpot_id)
        if sys_jackpot then
            sys_jackpot = tonumber(sys_jackpot) or 0
        else
            return false
        end

        --更新
        local beginvalue = sys_jackpot
        local endvalue = sys_jackpot + val
        redisdao.query_data(".gmmqredis", "hset", key, comment.jackpot_id, endvalue)

        --记录日志
        local change_type = EGateAction.ADD_JACKPOT   --奖池增加
        if val <= 0 then
            change_type = EGateAction.SUB_JACKPOT     --奖池减少
        end
        local logstr = string.format("%d,%d,%d,%g,%g,%g,%g,%g,%g,%s,%s,%s,%s", change_type, 0, 0, val, 0, 0, beginvalue, endvalue, 0, comment.jackpot_id, comment.start_time, comment.table_tradeid, gamename)
        if gametype == "diamond" then
            skynet.send(".diamondlog", "lua", "write", logstr)
        end

        return true
    end

    comment = comment or {}
    if val == 0 or not comment.jackpot_id then
        return false
    end

    --修改
    cs_jackpot[gamename] = cs_jackpot[gamename] or queue()
    local cs = cs_jackpot[gamename]
    local key = (gamename or "") .. "_system_jackpot"
    local gametype = string.match(gamename,"_(%a+)")

    return cs(real_update_system_jackpot, gametype, key, val, comment)
end

--
--发送玩家输赢变化
--
function SlotTool.send_player_changes(rid_values, comment)
    rid_values = rid_values or {}
    comment = comment or {}
    
    local nodename = string.match(comment.table_uuid or "","(.+)node_")
    
    local rid_changes = {}
    for rid,v in pairs(rid_values) do
        if v.real_change and tonumber(v.real_change) ~= tonumber(0) then
            rid_changes[rid] = v.real_change
        end
    end
    
    --发送玩家输赢
    if next(rid_changes) ~= nil then
        local change_cmd = {
            msghead = { msgname = "game_change" },
        	msgbody = {
                change_list = rid_changes,
                cur_time = timetool.get_time(),
                game_name = nodename,
                table_tradeid = comment.table_tradeid,
            }
        }
        redisdao.query_data(".gmmqredis", "rpush", "outchangemq", json.encode(change_cmd))
    end

    return true
end

return SlotTool
